package org.new9uy.tetris.model;

import org.new9uy.tetris.model.tetrimino.Tetrimino;

public class Score
{

    private boolean combo = false;
    private int score = 0;
    private int previousLines = 0; //number of lines done previously.
    private int totalLines = 0;
    private int lineFlag = 0; //previous lines done FLAG
    private int lineNetFlag = 0; //previous line done FLAG (for net)
    Matrix mtx;

    public Score(Matrix mtx)
    {
        this.mtx = mtx;
    }

    public boolean combo()
    {
        if (combo)
        {
            combo = false;
            return true;
        } else
        {
            return false;
        }
    }

    public int totalLinesDone()
    {
        return totalLines;
    }

    public int linesDone()
    {
        int ret = lineFlag;
        lineFlag = 0;
        return ret;
    }

    public int linesDoneNet()
    {
        int ret = lineNetFlag;
        lineNetFlag = 0;
        return ret;
    }

    public void addBonus(int points)
    {
        score += points;
    }

    public int getScore()
    {
        return score;
    }

    public void reset()
    {
        score = 0;
        totalLines = 0;
        lineFlag = 0;
        lineNetFlag = 0;
        combo = false;
        previousLines = 0;
    }

    public boolean checkLines(Tetrimino lastLanded, int gravLvl)
    {
        int[] linesCovered = mtx.getLines(lastLanded);
        int[] linesCounted = new int[linesCovered.length];
        int linesDone = 0;
        int j = 0;

        for (int i = 0; i < linesCovered.length; i++)
        {
            if (lineCounts(linesCovered[i]))
            {
                linesCounted[j] = linesCovered[i];
                linesDone++;
                j++;
            }
        }
        if (linesDone == 0)
        {
            return false;
        }
        for (int i = j; i < linesCounted.length; i++)
        {
            linesCounted[i] = -1;
        }

        if (linesDone == 4)
        {
            mtx.setLines();
        }
        if (linesDone > 1 && previousLines > 1 && (linesDone >= previousLines))
        {
            combo = true;
        }
        mtx.clearLines(linesCounted);
        lineFlag = linesDone; //For l'envoie de lignes
        lineNetFlag = linesDone;

        addBonus(scoreWithCombo(linesDone, gravLvl));
        previousLines = linesDone;
        totalLines += linesDone;
        return true;
    }

    private boolean lineCounts(int y)
    {
        for (int x = 1; x <= mtx.getXDim(); x++)
        {
            if (mtx.getMino(x, y).isEmpty())
            {
                return false;
            }
        }
        return true;
    }

    //Formula : Score = (lvl + 1) * a
    //  a := lines_value
    private int scoreFor(int lines, int gravLvl)
    {
        int a = 0;
        switch (lines)
        {
            case 0:
                return 0;
            case 1:
                a = 40;
                break;
            case 2:
                a = 100;
                break;
            case 3:
                a = 300;
                break;
            case 4:
                a = 1200;
                break;
            default:
                throw new IllegalArgumentException(lines + "is not an appropriate number for \"lines\". It "
                        + "must be an int from 0 to 4");
        }
        return (gravLvl + 1) * a;
    }

    private int scoreWithCombo(int lines, int gravLvl)
    {
        int points = scoreFor(lines, gravLvl);
        if (combo())
        {
            return points * 2;
        } else
        {
            return points;
        }
    }

    public void refreshScore(int score)
    {
        this.score = score;
    }

    public void refreshLinesDone(byte lines)
    {
        this.totalLines = lines;
    }

    public void refreshLineFlag(byte lines)
    {
        this.lineFlag = lines;
    }
}
